/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mindbox.mueblesalpes.negocio.persistence;

import com.mindbox.mueblesalpes.negocio.entity.TarjetaCredito;
import com.mindbox.mueblesalpes.negocio.exception.ErrorCommit;
import com.mindbox.mueblesalpes.negocio.exception.ErrorInitTransaction;
import com.mindbox.mueblesalpes.negocio.exception.NoSePudoGrabarTarjetaCredito;
import com.mindbox.mueblesalpes.negocio.exception.TarjetaCreditoNoExiste;
import com.mindbox.mueblesalpes.negocio.exception.TarjetaCreditoRepetida;
import com.mindbox.mueblesalpes.negocio.exception.TiendaException;
import com.mindbox.mueblesalpes.negocio.utilidades.UtilidadesTarjetaCredito;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.sql.DataSource;
import javax.transaction.UserTransaction;

/**
 * Bean que maneja la persistencia de la tarjeta de crédito.
 * @author jsanchez
 */
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class TarjetaCreditoBean implements TarjetaCreditoLocal {

    @Resource(mappedName = "jdbc/tiendaMindboxTC")
    private DataSource dataSource;
    @Resource
    private UserTransaction ut;

    @Override
    public void crearTarjetaCredito(TarjetaCredito tarjetaCredito) throws TarjetaCreditoRepetida, NoSePudoGrabarTarjetaCredito {
        try {
            UtilidadesPersistencia.initTransaction(ut);
            insertarTarjetaCredito(tarjetaCredito);
            UtilidadesPersistencia.commitTransaction(ut);
        } catch (NoSePudoGrabarTarjetaCredito ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw ex;
        } catch (TarjetaCreditoRepetida ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw ex;
        } catch (ErrorInitTransaction ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            throw new TiendaException("Error al iniciar la transacción de grabación de una tarjeta de crédito.");
        } catch (ErrorCommit ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw new TiendaException("Error al crear una Tarjeta de crédito.");
        } catch (SQLException ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw new TiendaException("Error al crear una Tarjeta de crédito.");
        }
    }

    /**
     * Inserta una tarjeta de crédito en la BD.
     * @param tarjetaCredito
     * @throws java.sql.SQLException
     * @throws com.mindbox.mueblesalpes.negocio.exception.TarjetaCreditoRepetida
     * @throws NoSePudoGrabarTarjetaCredito
     */
    private void insertarTarjetaCredito(TarjetaCredito tarjetaCredito) throws SQLException, TarjetaCreditoRepetida, NoSePudoGrabarTarjetaCredito {
        Connection conexion = null;
        PreparedStatement ps = null;
        try {
            conexion = dataSource.getConnection();
            conexion.setAutoCommit(false);
            if (!UtilidadesPersistencia.existeId(conexion, tarjetaCredito.getId(), "tarjeta_credito")) {
                String sql = "INSERT INTO TARJETA_CREDITO(ID, IDCLIENTE, MONTOTARJETA) VALUES(?,?,?)";
                ps = conexion.prepareStatement(sql);
                ps.setLong(1, tarjetaCredito.getId().longValue());
                ps.setLong(2, tarjetaCredito.getIdCliente().longValue());
                ps.setDouble(3, tarjetaCredito.getMontoTarjeta());
                if (ps.executeUpdate() != 1) {
                    throw new NoSePudoGrabarTarjetaCredito(tarjetaCredito);
                }
            } else {
                throw new TarjetaCreditoRepetida(tarjetaCredito.getId());
            }
        } finally {
            UtilidadesPersistencia.cerrarPreparedStatements(ps);
        }
    }

    @Override
    public TarjetaCredito getTarjetaCreditoFromIdCliente(Long idCliente) {
         Connection conexion = null;
        try {
            conexion = dataSource.getConnection();
            return UtilidadesTarjetaCredito.consultarTarjetaCreditoFromIdCliente(conexion, idCliente);
        } catch (SQLException ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            throw new TiendaException("Error al consultar una Tarjeta de crédito.");
        }finally{
            UtilidadesPersistencia.cerrarConexiones(conexion);
        }
    }

    @Override
    public TarjetaCredito getTarjetaCreditoFromId(Long id) {
        Connection conexion = null;
        try {
            conexion = dataSource.getConnection();
            return UtilidadesTarjetaCredito.consultarTarjetaCreditoFromId(conexion, id);
        } catch (SQLException ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            throw new TiendaException("Error al consultar una Tarjeta de crédito.");
        } finally {
            UtilidadesPersistencia.cerrarConexiones(conexion);
        }
    }

    @Override
    public void actualizarTarjetaCredito(TarjetaCredito tarjetaCredito) throws TarjetaCreditoNoExiste, NoSePudoGrabarTarjetaCredito{
        try {
            UtilidadesPersistencia.initTransaction(ut);
            updateTarjetaCredito(tarjetaCredito);
            UtilidadesPersistencia.commitTransaction(ut);
        } catch (NoSePudoGrabarTarjetaCredito ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw ex;
        } catch (TarjetaCreditoNoExiste ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw ex;
        } catch (ErrorInitTransaction ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            throw new TiendaException("Error al iniciar la transacción de actualización de una tarjeta de crédito.");
        } catch (ErrorCommit ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw new TiendaException("Error al actualizar una Tarjeta de crédito.");
        } catch (SQLException ex) {
            Logger.getLogger(TarjetaCreditoBean.class.getName()).log(Level.SEVERE, null, ex);
            UtilidadesPersistencia.rollBackTransaction(ut);
            throw new TiendaException("Error al actualizar una Tarjeta de crédito.");
        }
        
    }

    /**
    * Reemplaza el monto de una tarjeta de credito.
    * @param tarjetaCredito
    * @throws com.mindbox.mueblesalpes.negocio.exception.TarjetaCreditoNoExiste
    * @throws java.sql.SQLException
    * @throws com.mindbox.mueblesalpes.negocio.exception.NoSePudoGrabarTarjetaCredito
    */
    private void updateTarjetaCredito(TarjetaCredito tarjetaCredito) throws TarjetaCreditoNoExiste, SQLException, NoSePudoGrabarTarjetaCredito{
        Connection conexion = null;
        PreparedStatement ps = null;
        try {
            conexion = dataSource.getConnection();
            conexion.setAutoCommit(false);
            if(this.getTarjetaCreditoFromId(tarjetaCredito.getId()) != null ){
                String sql = 
                        "UPDATE TARJETA_CREDITO SET MONTOTARJETA = ? " +
                        "WHERE id = ?";
                ps = conexion.prepareStatement(sql);
                ps.setDouble(1, tarjetaCredito.getMontoTarjeta());
                ps.setLong(2, tarjetaCredito.getId().longValue());
                if (ps.executeUpdate() != 1)
                    throw new NoSePudoGrabarTarjetaCredito(tarjetaCredito);
            }
            else
                throw new TarjetaCreditoNoExiste(tarjetaCredito);
        } finally {
            UtilidadesPersistencia.cerrarPreparedStatements(ps);
        }
    }
}
